4. 密度プロット

4.1. 概要

密度プロットとは

4.2. Plotlyによる作図方法

Plotlyでは,plotly.figure_factory.create_distplot()でDensity plotを作成可能です.

import plotly.figure_factory as ff
fig = ff.create_distplot(
    df['x_col'].values.reshape(1, -1), 
    ['label'], show_hist=False)

上記の例では,dfcol_x列をX軸,その確率密度をY軸にとったDensity plotのオブジェクトfigを作成します. ただし,labelのように凡例名を指定する必要があることにご注意ください.

show_hist=False

plotly.figure_factory.create_distplot()はデフォルト設定でヒストグラムとDensity plotの両方を作図します.Density plotのみ表示したい場合は,show_hist=Falseを指定しましょう.

4.3. MADB Labを用いた作図例

4.3.1. 下準備

import pandas as pd
import plotly.figure_factory as ff
import plotly.express as px

import warnings
warnings.filterwarnings('ignore')
# 前処理の結果,以下に分析対象ファイルが格納されていることを想定
PATH_DATA = '../../data/preprocess/out/episodes.csv'
# Jupyter Book用のPlotlyのrenderer
RENDERER = 'plotly_mimetype+notebook'
# 平均掲載位置を算出する際の最小連載数
MIN_WEEKS = 5
def show_fig(fig):
    """Jupyter Bookでも表示可能なようRendererを指定"""
    fig.update_layout(margin=dict(t=50, l=25, r=25, b=25))
    fig.update_layout(legend={
        'yanchor': 'top',
        'xanchor': 'right',
        'x': 0.99, 'y': 0.99})
    fig.show(renderer=RENDERER)
df = pd.read_csv(PATH_DATA)

4.3.2. 掲載位置の分布

df_plot = \
    df.groupby(['mcname', 'cname', 'creator'])['pageStartPosition']\
    .agg(['count', 'mean']).reset_index()
df_plot = df_plot[df_plot['count'] >= MIN_WEEKS]\
    .reset_index(drop=True)
fig = ff.create_distplot(
    [df_plot['mean'].values], ['全作品'],
    show_hist=False)
show_fig(fig)

ヒストグラムで図示するよりも滑らかに分布を図示できていることがわかります.

4.3.3. 長期連載作品の掲載位置の分布

合計連載週数が多い5作品に対して,同様に分布を図示してみましょう.

df_tmp = \
    df_plot.sort_values(['count'], ascending=False, ignore_index=True)\
    .head(10)
df_tmp
mcname cname creator count mean
0 週刊少年ジャンプ こちら葛飾区亀有公園前派出所 秋本治 1866 0.612542
1 週刊少年マガジン はじめの一歩 森川ジョージ 1184 0.345121
2 週刊少年サンデー 名探偵コナン 青山剛昌 1008 0.175239
3 週刊少年ジャンプ ONE PIECE 尾田栄一郎 890 0.128448
4 週刊少年サンデー MAJOR 満田拓也 748 0.261425
5 週刊少年ジャンプ NARUTO-ナルト- 岸本斉史 722 0.191761
6 週刊少年ジャンプ BLEACH 久保帯人 715 0.411773
7 週刊少年ジャンプ 銀魂 空知英秋 652 0.447538
8 週刊少年チャンピオン ドカベン 水島新司 635 0.116675
9 週刊少年ジャンプ ジョジョの奇妙な冒険 荒木飛呂彦 594 0.625421
cnames = df_tmp.sort_values('mean')['cname'].values
data = [
    df[df['cname']==cname].reset_index(drop=True)\
    ['pageStartPosition'] for cname in cnames]
fig = ff.create_distplot(
    data, cnames, show_hist=False,
    colors= px.colors.sequential.Plasma_r)
fig.update_layout(hovermode='x unified', height=600)
show_fig(fig)

ヒストグラムと異なり,複数の凡例を同時に表示できるため,比較が楽です.

4.3.4. 長期連載作品の話数毎の掲載位置の分布

# 話数の区切り
UNIT_EP = 200
cnames = df_tmp.sort_values('mean')['cname'].values
for cname in cnames:
    df_c = df[df['cname']==cname].reset_index(drop=True)
    df_c['eprange'] = (df_c.index + 1) // UNIT_EP * UNIT_EP
    eps = sorted(df_c['eprange'].unique())
    data = [
        df_c[df_c['eprange']==e]['pageStartPosition']
        for e in eps]
    labels = [f'{e}話以降' for e in eps]
    fig = ff.create_distplot(
        data, labels, show_hist=False,
        colors= px.colors.sequential.Plasma_r)
    fig.update_layout(
        hovermode='x unified', height=500,
        title_text=f'{cname}の掲載位置')
    show_fig(fig)

積み上げヒストグラムを用いた場合より,話数による掲載位置の推移がわかりやすくなりました.